home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / System 7.0 Samples / DTS.Utilities / Utilities.inc1.p < prev    next >
Encoding:
Text File  |  1994-11-18  |  49.1 KB  |  1,751 lines  |  [TEXT/MPS ]

  1. {*****************************************************************************
  2. #
  3. #    Apple Macintosh Developer Technical Support
  4. #
  5. #    Collection of Utilities for DTS Sample code
  6. #
  7. #    Program:    Utilities.p.o
  8. #    File:        Utilities.inc1.p -    Pascal Implementation
  9. #
  10. #    Copyright © 1988-1990 Apple Computer, Inc.
  11. #    All rights reserved.
  12. #
  13. *****************************************************************************}
  14.  
  15. {[j=20/53/1$] Pasmat Options}
  16.  
  17. {*****************************************************************************}
  18.  
  19.  
  20.  
  21. {$S UtilMain}
  22. FUNCTION CenteredAlert(alertID: INTEGER; relatedWindow:WindowPtr): INTEGER;
  23.  
  24. { Given an alert ID and a window pointer the alert relates to, this function
  25.   will center the alert’s rectangle before showing it on the proper screen.
  26.   This follows the Apple Human Interface Guidelines for where to place a
  27.   centered window on the screen.  If the alert is not closely associated with
  28.   another window, pass a NIL for the window pointer of the related window.  If
  29.   you pass a NIL, the alert is simply displayed where the resource
  30.   would indicate.  Note that if an error occurs when getting the resource for
  31.   the alert, then the alert is not displayed, and the returned value is not
  32.   the item hit, but is the error that occured when reading the resource. }
  33.  
  34.     VAR
  35.         alertHandle:    AlertTHndl;
  36.         tempWindow:        WindowPtr;
  37.         alertRect:        Rect;
  38.         itemHit:        INTEGER;
  39.         hstate:            SignedByte;
  40.         err:            OSErr;
  41.  
  42.     BEGIN
  43.         alertHandle := AlertTHndl(GetAppResource('ALRT', alertID, err));
  44.         itemHit := err;
  45.  
  46.         if (err = noErr) THEN BEGIN
  47.             hstate := LockHandleHigh(Handle(alertHandle));
  48.                 { Do our part to help prevent fragmentation. }
  49.  
  50.             alertRect := alertHandle^^.boundsRect;
  51.                 { Preserve the real alert bounding rectangle. }
  52.  
  53.             tempWindow := NewWindow(NIL, alertRect, '', false, dBoxProc,
  54.                                     WindowPtr(NIL), false, 0);
  55.  
  56.             if tempWindow <> NIL THEN BEGIN
  57.                 { Use an invisible temporary window to calculate where the alert will go. }
  58.  
  59.                 alertHandle^^.boundsRect := CenterWindow(tempWindow, relatedWindow);
  60.                 DisposeWindow(tempWindow);
  61.             END;
  62.  
  63.             itemHit := Alert(alertID, ModalFilterProcPtr(NIL));
  64.             alertHandle^^.boundsRect := alertRect;
  65.                 { Restore the resource's bounding rect, so if this resource is ever used
  66.                   not through this function, it will open where the resource indicates. }
  67.  
  68.             HSetState(Handle(alertHandle), hstate);
  69.         END;
  70.  
  71.         CenteredAlert := itemHit;
  72.     END;
  73.  
  74.  
  75.  
  76. {*****************************************************************************}
  77.  
  78.  
  79.  
  80. {$S UtilMain}
  81. PROCEDURE CenterRectInRect(outerRect: Rect; VAR innerRect: Rect);
  82.  
  83. { Given two rects, this function centers the second one within the first. }
  84.  
  85.     BEGIN
  86.         PositionRectInRect(outerRect, innerRect, FixRatio (1, 2), FixRatio (1, 2));
  87.     END;
  88.  
  89.  
  90.  
  91. {*****************************************************************************}
  92.  
  93.  
  94.  
  95. {$S UtilMain}
  96. FUNCTION    CenterWindow(window:WindowPtr; relatedWindow:WindowPtr): Rect;
  97.  
  98. { Center a window within a particular device.  The device to center the window
  99.   within is determined by passing a related window.  This allows related
  100.   windows to be kept on the same device.  This is useful if an alert related
  101.   to a specific window, for example. }
  102.  
  103.     VAR
  104.         whichDevice:    WindowPtr;
  105.         deviceRect, oldWindowRect, newWindowRect, contentRect:    Rect;
  106.  
  107.     BEGIN
  108.         whichDevice := relatedWindow;
  109.         if whichDevice = NIL THEN
  110.             whichDevice := window;
  111.                 { If we have a window to center against, use the device for
  112.                   that window, else use the device for the window that is
  113.                   getting centered. }
  114.  
  115.         deviceRect := GetWindowDeviceRectNMB(whichDevice);
  116.             { We now have the rectangle of the device we want to center within. }
  117.  
  118.         newWindowRect := GetWindowStructureRect(window);
  119.         oldWindowRect := newWindowRect;
  120.  
  121.         PositionRectInRect(deviceRect, newWindowRect, FixRatio (1, 2), FixRatio (1, 3));
  122.             { Figure out the new window strucRect so we can compare it against
  123.               the old strucRect.  This will tell us how much to move the window. }
  124.  
  125.         contentRect := GetWindowContentRect(window);
  126.             { Get where the window is now. }
  127.  
  128.         OffsetRect(contentRect, newWindowRect.left - oldWindowRect.left,
  129.                                 newWindowRect.top  - oldWindowRect.top);
  130.             { Calculate the new content rect. }
  131.  
  132.         MoveWindow(window, contentRect.left, contentRect.top, false);
  133.             { Move the window to the new location. }
  134.  
  135.         CenterWindow := contentRect;
  136.     END;
  137.  
  138.  
  139.  
  140. {*****************************************************************************}
  141.  
  142. {$S UtilMain}
  143. PROCEDURE CloseAnyWindow(window: WindowPtr);
  144.  
  145. { Close a window.  This handles desk accessory and application windows.  Use
  146.   this call (instead of DisposeAnyWindow) if the memory for the window was
  147.   allocated by you.  (Same as CloseWindow v.s. DisposeWindow.) }
  148.  
  149.     BEGIN
  150.         IF IsDAWindow(window) THEN
  151.             CloseDeskAcc(WindowPeek(window)^.windowKind)
  152.         ELSE BEGIN
  153.             IF IsAppWindow(window) THEN
  154.                 CloseWindow(window)
  155.             ELSE
  156.                 IF WindowPeek(window)^.windowKind >= dialogKind THEN
  157.                     CloseDialog(DialogPtr(window));
  158.         END;
  159.     END;
  160.  
  161.  
  162.  
  163. {*****************************************************************************}
  164.  
  165. {$S UtilMain}
  166. PROCEDURE DisposeAnyWindow(window: WindowPtr);
  167.  
  168. { Dispose a window.  This handles desk accessory and application windows.  Use
  169.   this call (instead of CloseAnyWindow) if you want the memory for the window
  170.   record to be disposed of.  (Same as CloseWindow v.s. DisposeWindow.) }
  171.  
  172.     BEGIN
  173.         IF IsDAWindow(window) THEN
  174.             CloseDeskAcc(WindowPeek(window)^.windowKind)
  175.         ELSE BEGIN
  176.             IF IsAppWindow(window) THEN
  177.                 DisposeWindow(window)
  178.             ELSE
  179.                 IF WindowPeek(window)^.windowKind >= dialogKind THEN
  180.                     DisposeDialog(DialogPtr(window));
  181.         END;
  182.     END;
  183.  
  184. {*****************************************************************************}
  185.  
  186.  
  187.  
  188. {$S UtilMain}
  189. PROCEDURE DeathAlert(errResID: INTEGER; errStringIndex: INTEGER);
  190.  
  191. { Display an alert that tells the user an error occurred, then exit the
  192.   program. This routine is used as an ultimate bail-out for serious errors
  193.   that prohibit the continuation of the application. Errors that do not
  194.   require the termination of the application should be handled in a different
  195.   manner. }
  196.  
  197.     BEGIN
  198.         ErrorAlert(errResID, errStringIndex);
  199.         ExitToShell;
  200.     END;
  201.  
  202.  
  203.  
  204. {*****************************************************************************}
  205.  
  206.  
  207.  
  208. {$S UtilMain}
  209. PROCEDURE DeathAlertMessage(errResID, errStringIndex, message: INTEGER);
  210.  
  211. { Display an alert that tells the user an error occurred, then exit the
  212.   program. This routine is used as an ultimate bail-out for serious errors
  213.   that prohibit the continuation of the application. Errors that do not
  214.   require the termination of the application should be handled in a different
  215.   manner. }
  216.  
  217.     BEGIN
  218.         ErrorAlertMessage(errResID, errStringIndex, message);
  219.         ExitToShell;
  220.     END;
  221.  
  222.  
  223.  
  224. {*****************************************************************************}
  225.  
  226.  
  227.  
  228. {$S UtilMain}
  229. PROCEDURE ErrorAlert(errResID, errStringIndex: INTEGER);
  230.  
  231. { Display an alert that tells the user an error occurred. }
  232.  
  233.     BEGIN
  234.         ErrorAlertMessage(errResID, errStringIndex, 0);
  235.     END;
  236.  
  237.  
  238.  
  239. {*****************************************************************************}
  240.  
  241.  
  242.  
  243. {$S Main}
  244. PROCEDURE ErrorAlertMessage(errResID, errStringIndex, message: INTEGER);
  245.  
  246. { Display an alert to inform the user of an error. errStringIndex acts as an
  247.   index into a STR# resource of error messages. If no errStringIndex is given,
  248.   i.e. = 0, then use a standard message. If message is not noErr then display
  249.   it as well.
  250.  
  251.   BUG NOTE: GetIndString will return a bogus String if the index is not
  252.   positive. }
  253.  
  254.     VAR
  255.         msg1, msg2:         Str255;
  256.         itemHit:            INTEGER;
  257.  
  258.     BEGIN
  259.         SetCursor(qd.arrow);
  260.  
  261.         IF errStringIndex <= 0 THEN BEGIN
  262.             errStringIndex := eStandardErr;
  263.             errResID := rUtilStrings;
  264.         END;
  265.         GetIndString(msg1, errResID, errStringIndex);
  266.  
  267.         IF message = noErr THEN BEGIN
  268.             ParamText(msg1, '', '', '');
  269.             itemHit := CenteredAlert(rUtilErrorAlert, NIL);
  270.         END
  271.         ELSE BEGIN
  272.             NumToString(message, msg2);
  273.             ParamText(msg1, msg2, '', '');
  274.             itemHit := CenteredAlert(rUtilErrorMessageAlert, NIL);
  275.         END;
  276.     END;
  277.  
  278.  
  279.  
  280. {*****************************************************************************}
  281.  
  282.  
  283.  
  284. FUNCTION    FindSysFolder(VAR foundVRefNum:INTEGER; VAR foundDirID: LongInt): OSErr;
  285.     { FindSysFolder returns the (real) vRefNum, and the DirID of the current
  286.       system folder.  It uses the Folder Manager if present, otherwise 
  287.       it falls back to SysEnvirons.  It returns zero on success, otherwise 
  288.       a standard system error. }
  289.  
  290.     VAR
  291.         gesResponse:    LongInt;
  292.         envRec:            SysEnvRec;
  293.         myWDPB:            WDPBRec;
  294.         volName:        Str255;
  295.         err:            OSErr;
  296.  
  297.     BEGIN
  298.         foundVRefNum := 0;
  299.         foundDirID := 0;
  300.         IF (Gestalt (gestaltFindFolderAttr, gesResponse) = noErr) & 
  301.             (BTst (gesResponse, gestaltFindFolderPresent)) THEN BEGIN    { Does Folder Manager exist? }
  302.                 err := FindFolder (kOnSystemDisk, kSystemFolderType, kDontCreateFolder, 
  303.                 foundVRefNum, foundDirID)
  304.         END
  305.         ELSE BEGIN
  306.             { Gestalt can't give us the answer, so we resort to SysEnvirons }
  307.             err := SysEnvirons (curSysEnvVers, envRec);
  308.             IF err = noErr THEN BEGIN
  309.                 myWDPB.ioVRefNum := envRec.sysVRefNum;
  310.                 volName := '';                    { Zero volume name }
  311.                 myWDPB.ioNamePtr := @volName;
  312.                 myWDPB.ioWDIndex := 0;
  313.                 myWDPB.ioWDProcID := 0;
  314.                 err := PBGetWDInfo (@myWDPB, FALSE);
  315.                 IF err = noErr THEN BEGIN
  316.                     foundVRefNum := myWDPB.ioWDVRefNum;
  317.                     foundDirID := myWDPB.ioWDDirID
  318.                 END
  319.             END
  320.         END;
  321.  
  322.         FindSysFolder := err
  323.     END;
  324.  
  325.  
  326.  
  327. {*****************************************************************************}
  328.  
  329.  
  330.  
  331. {$S UtilMain}
  332. FUNCTION GetAppIndResource(theType: ResType;index: INTEGER; VAR err:OSErr): Handle;
  333.  
  334. { GetAppIndResource gets a resource from the application's resource file by index }
  335.     VAR
  336.         savedResFile:    INTEGER;
  337.     
  338.     BEGIN
  339.         savedResFile := CurResFile;
  340.         UseResFile (gAppResRef);
  341.         GetAppIndResource := Get1IndResource (theType, index);
  342.         err := ResError;
  343.         UseResFile (savedResFile)
  344.     END;            { GetAppIndResource }
  345.  
  346.  
  347.  
  348. {*****************************************************************************}
  349.  
  350.  
  351.  
  352. {$S UtilMain}
  353. FUNCTION GetAppNamedResource(theType: ResType;name: Str255; VAR err:OSErr): Handle;
  354.  
  355. { GetAppNamedResource gets a resource from the application's resource file by name }
  356.     VAR
  357.         savedResFile:    INTEGER;
  358.     
  359.     BEGIN
  360.         savedResFile := CurResFile;
  361.         UseResFile (gAppResRef);
  362.         GetAppNamedResource := Get1NamedResource (theType, name);
  363.         err := ResError;
  364.         UseResFile (savedResFile)
  365.     END;            { GetAppNamedResource }
  366.  
  367.  
  368.  
  369. {*****************************************************************************}
  370.  
  371.  
  372.  
  373. {$S UtilMain}
  374. FUNCTION GetAppResource(theType: ResType;theID: INTEGER; VAR err:OSErr): Handle;
  375.  
  376. { GetAppResource gets a resource from the application's resource file by resource ID }
  377.     VAR
  378.         savedResFile:    INTEGER;
  379.     
  380.     BEGIN
  381.         savedResFile := CurResFile;
  382.         UseResFile (gAppResRef);
  383.         GetAppResource := Get1Resource (theType, theID);
  384.         err := ResError;
  385.         UseResFile (savedResFile)
  386.     END;            { GetAppResource }
  387.  
  388.  
  389.  
  390. {*****************************************************************************}
  391.  
  392.  
  393.  
  394. {$S UtilMain}
  395. FUNCTION GetAUXVersion: INTEGER;
  396.  
  397. { GetAUXVersion -- Checks for the presence of A/UX by whatever means is appropriate.
  398.   Returns the major version number of A/UX (i.e. 0 if A/UX is not present, 1 for
  399.   any 1.x.x version 2 for any 2.x version, etc.
  400.  
  401.   This code should work for all past, present and future A/UX systems. }
  402.     
  403.     CONST
  404.         kHWCfgFlags         = $B22;                 {low memory hardware config flags}
  405.         kAUXbit                = 9;                    {bit set in kHWCfgFlags for A/UX}
  406.         kShiftHighByte        = 8;                    {shift 8 bits to the right}
  407.         kAUXnotRunning        = 0;                    {not running A/UX}
  408.         kDefaultVersion        = $100;                    {assumed version 1.x.x of A/UX}
  409.     
  410.     VAR
  411.         AUXversion:            LONGINT;
  412.         err:                INTEGER;
  413.     
  414.     BEGIN
  415.         err:= noErr;
  416.         AUXversion:= kAUXnotRunning;                {assume A/UX is not running}
  417.         err:= Gestalt(gestaltAUXVersion, AUXVersion);
  418.             
  419.         IF (err = gestaltUnknownErr) | (err = gestaltUndefSelectorErr) THEN BEGIN
  420.             IF BTst(IntegerPtr(kHWCfgFlags)^, kAUXbit) THEN
  421.                 AUXversion:= kDefaultVersion;        {A/UX is running, default version}
  422.         END;
  423.         GetAUXVersion:= BSR(AUXversion, kShiftHighByte);
  424.     END;
  425.  
  426.  
  427.  
  428. {*****************************************************************************}
  429.  
  430.  
  431.  
  432. {$S UtilMain}
  433. FUNCTION    GetCenteredDialog(id:INTEGER; storage: Ptr; 
  434.     relWindow, behind:WindowPtr): DialogPtr;
  435.  
  436. { Given a dialog ID and a window pointer the dialog relates to, this function
  437.   will center the dialog’s rectangle before showing it on the proper screen.
  438.   This follows the Apple Human Interface Guidelines for where to place a
  439.   centered window on the screen.  If the dialog is not closely associated with
  440.   another window, pass a nil for the window pointer of the related window.  If
  441.   you pass a nil, the dialog is simply displayed where the resource
  442.   would indicate. }
  443.  
  444.     VAR
  445.         dlogResource:    DialogTHndl;
  446.         dialog:            DialogPtr;
  447.         oldVis:            BOOLEAN;
  448.         hstate:            SignedByte;
  449.         err:            OSErr;
  450.         dummyRect:        Rect;
  451.     
  452.     BEGIN
  453.         dialog := NIL;
  454.         dlogResource := DialogTHndl(GetAppResource('DLOG', id, err));
  455.         if (dlogResource <> NIL) THEN BEGIN
  456.             hstate := LockHandleHigh(Handle(dlogResource));
  457.             oldVis := dlogResource^^.visible;
  458.             dlogResource^^.visible := false;
  459.             dialog := GetNewDialog(id, storage, behind);
  460.             if dialog <> NIL THEN BEGIN
  461.                 dummyRect := CenterWindow(dialog, relWindow);
  462.                 if oldVis = true THEN
  463.                     ShowWindow(dialog);
  464.             END;
  465.             dlogResource^^.visible := oldVis;
  466.             HSetState(Handle(dlogResource), hstate);
  467.         END;
  468.         GetCenteredDialog := dialog;
  469.     END;
  470.  
  471.  
  472.  
  473. {*****************************************************************************}
  474.  
  475.  
  476.  
  477. {$S UtilMain}
  478. FUNCTION    GetCenteredWindow(id:INTEGER; storage: Ptr; relWindow, behind: WindowPtr;
  479.     inColor:BOOLEAN): WindowPtr;
  480.  
  481. { Given a window ID and a window pointer the window relates to, this function
  482.   will center the window’s rectangle before showing it on the proper screen.
  483.   This follows the Apple Human Interface Guidelines for where to place a
  484.   centered window on the screen.  If the window is not closely associated with
  485.   another window, pass a nil for the window pointer of the related window.  If
  486.   you pass a nil, the window is simply displayed where the resource
  487.   would indicate. }
  488.  
  489.     BEGIN
  490.         GetCenteredWindow := GetSomeKindOfWindow(CenterWindow, id, storage, relWindow, 
  491.             behind, inColor);
  492.     END;
  493.  
  494.  
  495.  
  496. {*****************************************************************************}
  497.  
  498.  
  499.  
  500. {$S UtilMain}
  501. FUNCTION GetCheckOrRadio(dlgPtr: DialogPtr; itemNo: INTEGER): BOOLEAN;
  502.  
  503.     VAR
  504.         iKind:                INTEGER;
  505.         iHandle:            Handle;
  506.         iRect:                Rect;
  507.  
  508.     BEGIN
  509.         GetDialogItem(dlgPtr, itemNo, iKind, iHandle, iRect);
  510.         GetCheckOrRadio := GetControlValue(ControlHandle(iHandle)) <> 0;
  511.     END;
  512.  
  513.  
  514.  
  515. {*****************************************************************************}
  516.  
  517.  
  518.  
  519. {$S UtilMain}
  520. FUNCTION    GetGestaltResult (gestaltSelector: OSType): LongInt;
  521.  
  522. { GetGestaltResult returns the result value from Gestalt for the specified selector.
  523.     If Gestalt returned an error GetGestaltResult returns zero.  Use of this function
  524.     is only cool if we don't care whether Gestalt returned an error.  In many cases
  525.     you may need to know the exact Gestalt error code so then this routine would be
  526.     inappropriate.  See GetAUXVersion for example.}
  527.  
  528.     VAR
  529.         gestaltResult:    LongInt;
  530.  
  531.     BEGIN
  532.         IF Gestalt (gestaltSelector, gestaltResult) = noErr THEN
  533.             GetGestaltResult := gestaltResult
  534.         ELSE
  535.             GetGestaltResult := 0
  536.     END;
  537.  
  538.  
  539.  
  540. {*****************************************************************************}
  541.  
  542.  
  543.  
  544. {$S UtilMain}
  545. FUNCTION GetGlobalMouse: Point;
  546.  
  547. { Get the global coordinates of the mouse. When you call OSEventAvail it will
  548.   return either a pending event or a null event. In either case, the where
  549.   field of the event record will contain the current position of the mouse in
  550.   global coordinates and the modifiers field will reflect the current state of
  551.   the modifiers. Another way to get the global coordinates is to call GetMouse
  552.   and LocalToGlobal, but that requires being sure that thePort is set to a
  553.   valid port. }
  554.  
  555.     CONST
  556.         kNoEvents            = 0;
  557.  
  558.     VAR
  559.         event:                EventRecord;
  560.  
  561.     BEGIN
  562.         IF OSEventAvail(kNoEvents, event) THEN;     { we aren’t interested in any events }
  563.         GetGlobalMouse := event.where;                { just the mouse position }
  564.     END;                                            { GetGlobalMouse }
  565.  
  566.  
  567.  
  568. {*****************************************************************************}
  569.  
  570.  
  571.  
  572. {$S UtilMain}
  573. FUNCTION GetGlobalTopLeft(window: WindowPtr): Point;
  574.  
  575. { Given a window, this will return the top left point of the window’s port in
  576.   global coordinates. Something this doesn’t include is the window’s drag
  577.   region (or title bar). This returns the top left point of the window’s
  578.   content area only. }
  579.  
  580.     VAR
  581.         oldPort:            GrafPtr;
  582.         globalPt:            Point;
  583.  
  584.     BEGIN
  585.         GetPort(oldPort);
  586.         SetPort(window);
  587.         globalPt := window^.portRect.topLeft;
  588.         LocalToGlobal(globalPt);
  589.         SetPort(oldPort);
  590.         GetGlobalTopLeft := globalPt;
  591.     END;                                            { GetGlobalTopLeft }
  592.  
  593.  
  594.  
  595. {*****************************************************************************}
  596.  
  597.  
  598.  
  599. {$S UtilMain}
  600. FUNCTION GetKFreeSpace(vRefNum: INTEGER): LONGINT;
  601.  
  602. { Return the amount of free space on the volume in KBytes. This builds a
  603.   LONGINT based on an unsigned INTEGER, which looks like a negitive value to
  604.   Pascal.  -1 is return as the size if there is an error. }
  605.  
  606.     VAR
  607.         pb:                 HParamBlockRec;
  608.         convert:            TwoIntsMakesALong;
  609.         err:                OSErr;
  610.  
  611.     BEGIN
  612.         WITH pb DO BEGIN                            { set up the block for PBHGetVInfo }
  613.             ioNamePtr := NIL;                        { we don't care about the name }
  614.             ioVRefNum := vRefNum;
  615.             ioVolIndex := 0;                        { use ioVRefNum only }
  616.         END;                                        { with }
  617.         err := PBHGetVInfo(@pb, FALSE);
  618.  
  619.         IF (err = noErr) THEN BEGIN
  620.             convert.ints[0] := 0;
  621.             convert.ints[1] := pb.ioVFrBlk;
  622.             GetKFreeSpace := (convert.long * pb.ioVAlBlkSiz) DIV 1024;
  623.         END
  624.         ELSE                                        { we couldn't get free space size! }
  625.             GetKFreeSpace := - 1;
  626.     END;
  627.  
  628.  
  629.  
  630. {*****************************************************************************}
  631.  
  632.  
  633.  
  634. {$S UtilMain}
  635. FUNCTION GetMainScreenRect: Rect;
  636.  
  637.     VAR
  638.         mainDevice:         GDHandle;
  639.         mainPort:            GrafPtr;
  640.  
  641.     BEGIN
  642.         IF gQDVersion > kQDOriginal THEN BEGIN
  643.             mainDevice := GetMainDevice;
  644.             GetMainScreenRect := mainDevice^^.gdRect;
  645.         END
  646.         ELSE BEGIN
  647.             GetWMgrPort(mainPort);
  648.             GetMainScreenRect := mainPort^.portRect;
  649.         END;
  650.     END;
  651.  
  652.  
  653.  
  654. {*****************************************************************************}
  655.  
  656.  
  657.  
  658. {$S UtilMain}
  659. FUNCTION GetRectDevice(globalRect: Rect): GDHandle;
  660.  
  661. { Find the greatest overlap device for the given global rectangle. }
  662.  
  663.     VAR
  664.         area:                LONGINT;
  665.         maxArea:            LONGINT;
  666.         device:             GDHandle;
  667.         intersection:        Rect;
  668.  
  669.     BEGIN                                            {GetRectDevice}
  670.         GetRectDevice := GetMainDevice;                { Use as default choice. }
  671.         maxArea := 0;
  672.  
  673.         device := GetDeviceList;
  674.         WHILE device <> NIL DO BEGIN
  675.             IF TestDeviceAttribute(device, screenDevice) & TestDeviceAttribute(device,
  676.                screenActive) & SectRect(globalRect, device^^.gdRect, intersection) THEN BEGIN
  677.                 WITH intersection DO
  678.                     area := LONGINT(right - left) * LONGINT(bottom - top);
  679.                 IF area > maxArea THEN BEGIN
  680.                     GetRectDevice := device;
  681.                     maxArea := area;
  682.                 END;                                {IF area > maxArea}
  683.             END;                                    {IF TestDeviceAttribute…}
  684.             device := GetNextDevice(device);
  685.         END;                                        {WHILE device <> NIL}
  686.     END;                                            {GetRectDevice}
  687.  
  688.  
  689.  
  690. {*****************************************************************************}
  691.  
  692.  
  693.  
  694. {$S UtilMain}
  695. FUNCTION    GetRectDeviceRect(globalRect: Rect): Rect;
  696.  
  697. { Find the rect of the greatest overlap device for the given global rect. }
  698.  
  699.     VAR
  700.         device:    GDHandle;
  701.  
  702.     BEGIN
  703.         IF gQDVersion > kQDOriginal THEN BEGIN
  704.             device := GetRectDevice(globalRect);
  705.             GetRectDeviceRect := device^^.gdRect;
  706.         END
  707.         ELSE
  708.             GetRectDeviceRect := GetMainScreenRect;
  709.     END;
  710.  
  711.  
  712.  
  713. {*****************************************************************************}
  714.  
  715.  
  716.  
  717. {$S UtilInit}
  718. FUNCTION    GetSomeKindOfWindow(FUNCTION whatKind(window, relWindow:WindowPtr):Rect; 
  719.     windID:INTEGER; storage: Ptr; relWindow, behind:WindowPtr; inColor:BOOLEAN):WindowPtr;
  720.  
  721. { Given a window positioning procedure pointer, a window ID and a window
  722.   pointer the window relates to, this function open a new window by either
  723.   a NewCWindow or a NewWindow call, depending on the value of inColor.  The
  724.   window will be opened invisible, independent of what the resource says.
  725.   Once the window is opened successfully, the positioning procedure is
  726.   called.  The positioning procedure is passed a pointer to the just-opened
  727.   invisible window and a pointer to the related window.  It is up to the
  728.   positioning procedure to move the invisible window to the correct location
  729.   on the correct device.  Once the positioning procedure returns, the window
  730.   will be made visible if so indicated by the resource. }
  731.  
  732.     VAR
  733.         windowResource:    WindowTHndl;
  734.         wt:                WindowTemplate;
  735.         aWindow:        WindowPtr;
  736.         err:            OSErr;
  737.         dummyRect:        Rect;
  738.  
  739.     BEGIN
  740.         if gQDVersion = kQDOriginal THEN
  741.             inColor := false;
  742.  
  743.         aWindow := nil;        { Assume we will fail.  (Good attitude.) }
  744.         if storage = NIL THEN
  745.             storage := Ptr(NewPtr(sizeof(WindowRecord)));
  746.  
  747.         if storage <> NIL THEN BEGIN
  748.             { If we can allocate the memory for the window record... }
  749.  
  750.             windowResource := WindowTHndl(GetAppResource('WIND', windID, err));
  751.             if windowResource <> NIL THEN BEGIN
  752.                 { If we can load the window resource... }
  753.  
  754.                 wt := windowResource^^;        { Make local copy of resource. }
  755.  
  756.                 if inColor = true THEN        { Open either a regular or color window. }
  757.                     aWindow := NewCWindow(storage, wt.boundsRect, wt.title, false,
  758.                                           wt.procID, behind, wt.goAwayFlag, wt.refCon)
  759.                 ELSE
  760.                     aWindow := NewWindow(storage, wt.boundsRect, wt.title, false,
  761.                                          wt.procID, behind, wt.goAwayFlag, wt.refCon);
  762.  
  763.                 if aWindow <> NIL THEN BEGIN    { If we were able to open a window... }
  764.                     dummyRect := whatKind(aWindow, relWindow);
  765.                         { Call the designated window positioning procedure. }
  766.  
  767.                     if wt.visible THEN
  768.                         ShowWindow(aWindow);
  769.                             { If resource says window should be visible, do it. }
  770.                 END;
  771.             END;
  772.             if aWindow = NIL THEN
  773.                 DisposePtr(Ptr(storage));
  774.                     { If we failed, then get rid of window record memory. }
  775.         END;
  776.  
  777.         GetSomeKindOfWindow := aWindow;
  778.     END;
  779.  
  780.  
  781.  
  782. {*****************************************************************************}
  783.  
  784.  
  785.  
  786. {$S UtilInit}
  787. FUNCTION    GetStaggeredWindow(id:INTEGER; storage: Ptr; 
  788.     relWindow,behind:WindowPtr; inColor:BOOLEAN):WindowPtr;
  789.  
  790. { Given a window ID and a window pointer the window relates to, this function
  791.   will stagger the window’s rectangle before showing it on the proper screen.
  792.   This follows the Apple Human Interface Guidelines for where to place a
  793.   staggered window on the screen.  If the window is not closely associated
  794.   with another window, pass a nil for the window pointer of the related
  795.   window.  If you pass a nil, the window is simply displayed where the
  796.   resource would indicate. }
  797.  
  798.     BEGIN
  799.         GetStaggeredWindow := GetSomeKindOfWindow(StaggerWindow, id, storage, relWindow, behind, inColor);
  800.     END;
  801.  
  802.  
  803.  
  804. {*****************************************************************************}
  805.  
  806.  
  807.  
  808. {$S UtilInit}
  809. FUNCTION GetTrapType(theTrap: INTEGER): TrapType;
  810.  
  811. { Determines the type of a trap based on its trap number. If bit 11 is clear,
  812.   then it is an OS trap. Otherwise, it is a Toolbox trap. }
  813.  
  814.     BEGIN
  815.         { OS traps start with A0, Tool with A8 or AA. }
  816.         IF BAND(theTrap, $0800) = 0 THEN            { per D.A }
  817.             GetTrapType := OSTrap
  818.         ELSE
  819.             GetTrapType := ToolTrap;
  820.     END;                                            { GetTrapType }
  821.  
  822.  
  823.  
  824. {*****************************************************************************}
  825.  
  826.  
  827.  
  828. {$S UtilInit}
  829. FUNCTION    GetWindowContentRect(window:WindowPtr):Rect;
  830.  
  831. { Given a window pointer, return the global rectangle that encloses the
  832.   content area of the window. }
  833.  
  834.     VAR
  835.         oldPort:        WindowPtr;
  836.         contentRect:    Rect;
  837.  
  838.     BEGIN
  839.         GetPort(oldPort);
  840.         SetPort(window);
  841.         contentRect := window^.portRect;
  842.         LocalToGlobalRect(contentRect);
  843.         SetPort(oldPort);
  844.         GetWindowContentRect := contentRect;
  845.     END;
  846.  
  847.  
  848.  
  849. {*****************************************************************************}
  850.  
  851.  
  852.  
  853. {$S UtilMain}
  854. FUNCTION    GetWindowCount(includeDAs,includeInvisibles:BOOLEAN):INTEGER;
  855.  
  856. { This procedure counts the number of windows in the application plane.
  857.   You have the choices of also including DAs and invisible windows in
  858.   this count. }
  859.  
  860.     VAR
  861.         window:        WindowPeek;
  862.         count:        INTEGER;
  863.  
  864.     BEGIN
  865.         count  := 0;
  866.         window := WindowPeekPtr(LMGetWindowList)^;
  867.  
  868.         WHILE window <> NIL DO BEGIN
  869.  
  870.             if (window^.windowKind < 0) and (includeDAs = false) THEN
  871.             ELSE
  872.                 if (window^.visible = true) and (includeInvisibles = true) THEN
  873.                     count := count + 1;
  874.  
  875.             window := window^.nextWindow;
  876.         END;
  877.  
  878.         GetWindowCount := count;
  879.     END;
  880.  
  881.  
  882.  
  883. {*****************************************************************************}
  884.  
  885.  
  886.  
  887. {$S UtilMain}
  888. FUNCTION    GetWindowDevice(window:WindowPtr):GDHandle;
  889.  
  890. { Find the greatest overlap device for the given window. }
  891.  
  892.     BEGIN
  893.         GetWindowDevice := GetRectDevice(GetWindowStructureRect(window));
  894.     END;
  895.  
  896.  
  897.  
  898. {*****************************************************************************}
  899.  
  900.  
  901.  
  902. {$S UtilMain}
  903. FUNCTION    GetWindowDeviceRect(window:WindowPtr):Rect;
  904.  
  905. { Given a window pointer, find the device that contains most of the window
  906.   and return the device's bounding rectangle. }
  907.  
  908.     BEGIN
  909.         if gQDVersion > kQDOriginal THEN
  910.             GetWindowDeviceRect := GetWindowDevice(window)^^.gdRect
  911.         ELSE
  912.             GetWindowDeviceRect := GetMainScreenRect;
  913.     END;
  914.  
  915.  
  916.  
  917. {*****************************************************************************}
  918.  
  919.  
  920.  
  921. {$S UtilMain}
  922. FUNCTION    GetWindowDeviceRectNMB(window:WindowPtr):Rect;
  923.  
  924. { Given a window pointer, find the device that contains most of the window
  925.   and return the device's bounding rectangle.  If this device is the main
  926.   device, then remove the menubar area from the rectangle. }
  927.  
  928.     VAR
  929.         deviceRect, tempRect:    Rect;
  930.  
  931.     BEGIN
  932.         deviceRect := GetWindowDeviceRect(window);
  933.         tempRect := GetMainScreenRect;
  934.         if (EqualRect(deviceRect, tempRect) = true) THEN
  935.             deviceRect.top := deviceRect.top + GetMBarHeight;
  936.  
  937.         GetWindowDeviceRectNMB := deviceRect;
  938.     END;
  939.  
  940.  
  941.  
  942. {*****************************************************************************}
  943.  
  944.  
  945.  
  946. {$S UtilMain}
  947. FUNCTION    GetWindowStructureRect(window:WindowPtr):Rect;
  948.  
  949. { This procedure is used to get the rectangle that surrounds the entire
  950.   structure of a window.  This is true whether or not the window is visible.
  951.   If the window is visible, then it is a simple matter of using the bounding
  952.   rectangle of the structure region.  If the window is invisible, then the
  953.   strucRgn is not correct.  To make it correct, then window has to be moved
  954.   way off the screen and then made visible.  This generates a valid strucRgn,
  955.   although it is valid for the position that is way off the screen.  It still
  956.   needs to be offset back into the original position.  Once the bounding
  957.   rectangle for the strucRgn is obtained, the window can then be hidden again
  958.   and moved back to its correct location.  Note that ShowHide is used,
  959.   instead of ShowWindow and HideWindow.  HideWindow can change the plane of
  960.   the window.  Also, ShowHide does not affect the hiliting of windows. }
  961.  
  962.     VAR
  963.         oldPort:        GrafPtr;
  964.         structureRect:    Rect;
  965.         windowLoc:        Point;
  966.     
  967.     BEGIN
  968.         if WindowPeek(window)^.visible = true THEN
  969.             structureRect := WindowPeek(window)^.strucRgn^^.rgnBBox
  970.         ELSE BEGIN
  971.             GetPort(oldPort);
  972.             SetPort(window);
  973.             windowLoc := GetGlobalTopLeft(window);
  974.             MoveWindow(window, windowLoc.h, kOffscreenLoc, false);
  975.             ShowHide(window, true);
  976.             structureRect := WindowPeek(window)^.strucRgn^^.rgnBBox;
  977.             ShowHide(window, false);
  978.             MoveWindow(window, windowLoc.h, windowLoc.v, false);
  979.             SetPort(oldPort);
  980.             OffsetRect(structureRect, 0, windowLoc.v - kOffscreenLoc);
  981.         END;
  982.  
  983.         GetWindowStructureRect := structureRect;
  984.     END;
  985.  
  986.  
  987.  
  988. {*****************************************************************************}
  989.  
  990.  
  991.  
  992. {$S UtilMain}
  993. PROCEDURE GlobalToLocalRect(VAR aRect: Rect);
  994.  
  995.     BEGIN
  996.         GlobalToLocal(aRect.topLeft);
  997.         GlobalToLocal(aRect.botRight);
  998.     END;
  999.  
  1000.  
  1001.  
  1002. {*****************************************************************************}
  1003.  
  1004.  
  1005.  
  1006. {$S UtilInit}
  1007. PROCEDURE InitToolBox;
  1008.  
  1009.     BEGIN
  1010.         InitGraf(@qd.thePort);
  1011.         InitFonts;
  1012.         InitWindows;
  1013.         InitMenus;
  1014.         TEInit;
  1015.         InitDialogs(NIL);
  1016.         InitCursor;
  1017.     END;
  1018.  
  1019.  
  1020.  
  1021. {*****************************************************************************}
  1022.  
  1023.  
  1024.  
  1025. {$S UtilInit}
  1026. PROCEDURE InitUtilities;
  1027.  
  1028. { InitUtilities sets up some global variables for use by the utilities package.  If you call
  1029.    StandardInitialization, you don't need to call this, as it will do it for you. } 
  1030.  
  1031.     TYPE
  1032.         OSTypePtr            = ^OSType;
  1033.  
  1034.     VAR
  1035.         apParam:            Handle;
  1036.         bndlResource:        Handle;
  1037.         err:                OSErr;
  1038.  
  1039.     BEGIN
  1040.         gUtilitiesInited := FALSE;
  1041.  
  1042.         { Init all the Gestalt variables }
  1043.         gMachineType := GetGestaltResult (gestaltMachineType);
  1044.         gSystemVersion := GetGestaltResult (gestaltSystemVersion);
  1045.         gProcessorType := GetGestaltResult (gestaltProcessorType);
  1046.  
  1047.         { We only concern ourselves with there being an FPU, not which type it is }
  1048.         gHasFPU := (GetGestaltResult (gestaltFPUType) <> gestaltNoFPU);
  1049.  
  1050.         { We only concern ourselves with the major QD version number
  1051.           0 for original QD, 1 for 8-bit color QD, and 2 for 32-bit QD }
  1052.         gQDVersion := BAND ((BSR (GetGestaltResult (gestaltQuickdrawVersion), 8)), $FF);
  1053.         gKeyboardType := GetGestaltResult (gestaltKeyboardType);
  1054.         gAppleTalkVersion := GetGestaltResult (gestaltAppleTalkVersion);
  1055.  
  1056.         { We only concern ourselves with there being an PMMU, not which type it is }
  1057.         gHasPMMU := (GetGestaltResult (gestaltMMUType) >= gestalt68851);
  1058.         gAUXVersion := getAUXVersion;
  1059.  
  1060.         gHasWaitNextEvent := TrapExists(_WaitNextEvent);
  1061.         gInBackground := FALSE;
  1062.  
  1063.         GetAppParms(gAppName, gAppResRef, apParam);
  1064.  
  1065.         bndlResource := GetAppIndResource('BNDL', 1, err);
  1066.         IF (bndlResource <> NIL) THEN
  1067.             gSignature := OSTypePtr(bndlResource^)^
  1068.         ELSE
  1069.             gSignature := '????';
  1070.  
  1071.         gUtilitiesInited := TRUE;
  1072.     END;
  1073.  
  1074.  
  1075.  
  1076. {*****************************************************************************}
  1077.  
  1078.  
  1079.  
  1080. {$S UtilMain}
  1081. FUNCTION IsAppWindow(window: WindowPtr): BOOLEAN;
  1082.  
  1083. { Check to see if a window belongs to the application. If the window pointer
  1084.   passed was NIL, then it could not be an application window. WindowKinds that
  1085.   are negative belong to the system and windowKinds less than userKind are
  1086.   reserved by Apple except for windowKinds equal to dialogKind, which mean it
  1087.   is a dialog. }
  1088.  
  1089.     BEGIN
  1090.         IF window = NIL THEN
  1091.             IsAppWindow := FALSE
  1092.         ELSE
  1093.             IsAppWindow := (WindowPeek(window)^.windowKind >= userKind);
  1094.     END;                                            { IsAppWindow }
  1095.  
  1096.  
  1097.  
  1098. {*****************************************************************************}
  1099.  
  1100.  
  1101.  
  1102. {$S UtilMain}
  1103. FUNCTION IsDAWindow(window: WindowPtr): BOOLEAN;
  1104.  
  1105. { Check if a window belongs to a desk accessory. This will first test for a
  1106.   NIL window. DAs will have a negative windowKind. }
  1107.  
  1108.     BEGIN
  1109.         IF window = NIL THEN
  1110.             IsDAWindow := FALSE
  1111.         ELSE                                        { DA windows have negative windowKinds }
  1112.             IsDAWindow := (WindowPeek(window)^.windowKind < 0);
  1113.     END;                                            { IsDAWindow }
  1114.  
  1115.  
  1116.  
  1117. {*****************************************************************************}
  1118.  
  1119.  
  1120.  
  1121. {$S UtilMain}
  1122. PROCEDURE LocalToGlobalRect(VAR aRect: Rect);
  1123.  
  1124.     BEGIN
  1125.         LocalToGlobal(aRect.topLeft);
  1126.         LocalToGlobal(aRect.botRight);
  1127.     END;
  1128.  
  1129.  
  1130.  
  1131. {*****************************************************************************}
  1132.  
  1133.  
  1134.  
  1135. {$S UtilMain}
  1136. FUNCTION LockHandleHigh(theHandle: UNIV Handle):SignedByte;
  1137.  
  1138.     BEGIN
  1139.         LockHandleHigh := HGetState(theHandle);
  1140.         MoveHHi(theHandle);
  1141.         HLock(theHandle);
  1142.     END;
  1143.  
  1144.  
  1145.  
  1146. {*****************************************************************************}
  1147.  
  1148.  
  1149.  
  1150. {$S UtilInit}
  1151. FUNCTION NumToolboxTraps: INTEGER;
  1152.  
  1153. { InitGraf is always implemented (trap $A86E). If the trap table is big
  1154.   enough, trap $AA6E will always point to either Unimplemented or some other
  1155.   trap, but will never be the same as InitGraf. Thus, you can check the size
  1156.   of the trap table by asking if the address of trap $A86E is the same as
  1157.   $AA6E. }
  1158.  
  1159.     BEGIN
  1160.         IF NGetTrapAddress(_InitGraf, ToolTrap) = NGetTrapAddress($AA6E, ToolTrap) THEN
  1161.             NumToolboxTraps := $200
  1162.         ELSE
  1163.             NumToolboxTraps := $400;
  1164.     END;                                            { NumToolboxTraps }
  1165.  
  1166.  
  1167. {*****************************************************************************}
  1168.  
  1169.  
  1170.  
  1171. {$S UtilMain}
  1172. PROCEDURE OutlineControl(button: UNIV ControlHandle);
  1173.  
  1174. {Given any control handle, this will draw an outline around it.  This is
  1175.  used for the default button of a window.  The extra nice feature here is
  1176.  that I’ll erase the outline for buttons that are inactive.  Seems like
  1177.  there should be a Toolbox call for getting a control’s hilite state.
  1178.  Since there isn’t, I have to look into the control record myself.    This
  1179.  should be called for update and activate events.
  1180.  
  1181.  The method for determining the oval diameters for the roundrect is a
  1182.  little different than that recommended by Inside Mac.    IM I-407 suggests
  1183.  that you use a hardcoded (16,16) for the diameters. However, this only
  1184.  looks good for small roundrects. For larger ones, the outline doesn’t
  1185.  follow the inner roundrect because the CDEF for simply buttons doesn’t
  1186.  use (16,16). Instead, it uses half the height of the button as the
  1187.  diameter. By using this formula, too, our outlines look better.
  1188.  
  1189.  WARNING: This will set the current port to the control’s window.}
  1190.  
  1191.     VAR
  1192.         theRect:            Rect;
  1193.         curPen:             PenState;
  1194.         buttonOval:         INTEGER;
  1195.  
  1196.     BEGIN
  1197.         IF button <> NIL THEN BEGIN
  1198.             SetPort(button^^.contrlOwner);
  1199.             GetPenState(curPen);
  1200.             PenNormal;
  1201.             theRect := button^^.contrlRect;
  1202.             InsetRect(theRect, kButtonFrameInset, kButtonFrameInset);
  1203.             buttonOval := ((theRect.bottom - theRect.top) DIV 2)  + 2;
  1204.             IF (button^^.contrlHilite = kCntlActivate) THEN
  1205.                 PenPat(qd.black)
  1206.             ELSE
  1207.                 PenPat(qd.gray);
  1208.             PenSize(kButtonFrameSize, kButtonFrameSize);
  1209.             FrameRoundRect(theRect, buttonOval, buttonOval);
  1210.             SetPenState(curPen);
  1211.         END;
  1212.     END;
  1213.  
  1214. {*****************************************************************************}
  1215.  
  1216.  
  1217.  
  1218. {$S UtilMain}
  1219. PROCEDURE OutlineDialogItem(dlgPtr: DialogPtr; item: INTEGER);
  1220.  
  1221.     VAR
  1222.         iKind:                INTEGER;
  1223.         iHandle:            Handle;
  1224.         iRect:                Rect;
  1225.  
  1226.     BEGIN
  1227.         GetDialogItem(dlgPtr, item, iKind, iHandle, iRect);
  1228.         OutlineControl(iHandle);
  1229.     END;
  1230.  
  1231.  
  1232.  
  1233. {*****************************************************************************}
  1234.  
  1235.  
  1236.  
  1237. {$S UtilMain}
  1238. PROCEDURE PositionRectInRect(outerRect: Rect; VAR innerRect: Rect; horzRatio, vertRatio: Fixed);
  1239.  
  1240. { Given two rectangles, this routine positions the second within the first one
  1241.   so that the it maintains the spacing specified by the horzRatio and vertRatio
  1242.   parameters. In other words, to center an inner rectangle hoizontally, but
  1243.   have its center be 1/3 from the top of the outer rectangle, call this
  1244.   routine with horzRatio = FixRatio (1, 2), vertRatio = FixRatio (1, 3).  We use
  1245.   Fixed rather than floating point to avoid complications when mixing MC68881/non-MC68881
  1246.   versions of Utilities. }
  1247.  
  1248.     VAR
  1249.         outerRectHeight:    INTEGER;
  1250.         outerRectWidth:     INTEGER;
  1251.         innerRectHeight:    INTEGER;
  1252.         innerRectWidth:     INTEGER;
  1253.         yLocation:            INTEGER;
  1254.         xLocation:            INTEGER;
  1255.  
  1256.     BEGIN
  1257.         outerRectHeight := outerRect.bottom - outerRect.top;
  1258.         outerRectWidth := outerRect.right - outerRect.left;
  1259.  
  1260.         innerRectHeight := innerRect.bottom - innerRect.top;
  1261.         innerRectWidth := innerRect.right - innerRect.left;
  1262.  
  1263.         yLocation := Fix2Long (FixMul (Long2Fix (outerRectHeight - innerRectHeight), vertRatio))
  1264.             + outerRect.top;
  1265.         xLocation := Fix2Long (FixMul (Long2Fix (outerRectWidth - innerRectWidth), horzRatio))
  1266.             + outerRect.left;
  1267.         WITH innerRect DO BEGIN
  1268.             top := yLocation;
  1269.             left := xLocation;
  1270.             bottom := yLocation + innerRectHeight;
  1271.             right := xLocation + innerRectWidth;
  1272.         END;
  1273.     END;
  1274.  
  1275.  
  1276.  
  1277. {*****************************************************************************}
  1278.  
  1279.  
  1280.  
  1281. {$S UtilInit}
  1282. PROCEDURE PullApplicationToFront;
  1283.  
  1284.     CONST
  1285.         kBroughtToFront     = 3;
  1286.  
  1287.     VAR
  1288.         count:                INTEGER;
  1289.         event:                EventRecord;
  1290.         ignoreResult:        BOOLEAN;
  1291.  
  1292.     BEGIN
  1293.     { This code is necessary to pull the application into the foreground.  I use
  1294.       EventAvail because I don’t want to remove any events the user may have done,
  1295.       such as typing ahead.  Until the application has made a few calls (3 seems
  1296.       to be the magic number) to the Event Manager, MultiFinder keeps me in the
  1297.       background.    Splashscreens and Alerts will remain in a background layer
  1298.       until we get a few events.  This is documented in Tech Note #180.}
  1299.  
  1300.         FOR count := 1 TO kBroughtToFront DO
  1301.             ignoreResult := EventAvail(everyEvent, event);
  1302.     END;
  1303.  
  1304.  
  1305.  
  1306. {*****************************************************************************}
  1307.  
  1308.  
  1309.  
  1310. {$S UtilMain}
  1311. PROCEDURE SelectButton(button: UNIV ControlHandle);
  1312.  
  1313. { Given the button control handle, this will cause the button to look as if it
  1314.   has been clicked in. This is nice to do for the user if they type return or
  1315.   enter to select the default item.}
  1316.  
  1317.     VAR
  1318.         finalTicks:         LONGINT;
  1319.  
  1320.     BEGIN
  1321.         HiliteControl(button, kSelect);
  1322.         Delay(kDelayTime, finalTicks);
  1323.         HiliteControl(button, kDeselect);
  1324.     END;                                            { SelectButton }
  1325.  
  1326.  
  1327.  
  1328. {*****************************************************************************}
  1329.  
  1330.  
  1331.  
  1332. {$S UtilMain}
  1333. PROCEDURE SetCheckOrRadioButton(dlgPtr: DialogPtr; itemNo: INTEGER; state: INTEGER);
  1334.  
  1335. { Handy routine for setting the value of a radio button. Given a dialog
  1336.   pointer, and item number, and a state, this routine will take care of the
  1337.   rest. }
  1338.  
  1339.     VAR
  1340.         iKind:                INTEGER;
  1341.         iHandle:            Handle;
  1342.         iRect:                Rect;
  1343.  
  1344.     BEGIN
  1345.         GetDialogItem(dlgPtr, itemNo, iKind, iHandle, iRect);
  1346.         SetControlValue(ControlHandle(iHandle), state);
  1347.     END;
  1348.  
  1349.  
  1350.  
  1351. {*****************************************************************************}
  1352.  
  1353.  
  1354.  
  1355. {$S UtilMain}
  1356. FUNCTION    StaggerWindow(window,relatedWindow:WindowPtr):Rect;
  1357.  
  1358. { This algorithm for staggering windows does quite a good job.  It also is
  1359.   quite gnarly.  Here's the deal:
  1360.   There are pre-designated positions that we will try when positioning a
  1361.   window.  These slots will be tried from the upper-left corner towards the
  1362.   lower-right corner.  If there are other windows in that slot, then we will
  1363.   consider that slot taken, and proceed to the next slot.  A slot is
  1364.   determined to be taken by checking a point with a slop area.  This slop
  1365.   area is diamond-shaped, not simply rectangular.  If there is no other
  1366.   visible window with an upper-left corner within the slopt diamond, then
  1367.   we are allowed to position our window there.
  1368.   The above rule holds true unless this forces the window to be partly
  1369.   off the screen.  If the window ends up partly off the screen, then we try
  1370.   a new diagonal just below the first diagonal we tried.  We keep trying
  1371.   lower and lower diagonals until we find a spot for the window, or the
  1372.   diagonal doesn't fit on the screen at all.  If the diagonal doesn't fit,
  1373.   then we try diagonals to the right of the first diagonal.  If even this
  1374.   doesn't work, then we give up and put the window in the original spot
  1375.   we tried. }
  1376.  
  1377.     VAR
  1378.         whichDevice:                                WindowPtr;
  1379.         deviceRect, oldWindowRect, newWindowRect,
  1380.         slot1, contentRect:                            Rect;
  1381.         contained, finis:                            BOOLEAN;
  1382.         vertDirection, dummyBoolean:                BOOLEAN;
  1383.         diamondSize, diagNum, slotNum:                INTEGER;
  1384.  
  1385.         { WalkDiagonal traverses an imaginary line which is roughly diagonal starting at
  1386.           a point determined by diagNum.  It checks successive slots along that line for
  1387.           a slot (who's size is determined by diamondSize) which is not occupied by a
  1388.           window.  It returns true if it successfully finds such a slot.  foundWindowRect
  1389.           is set to the appropriate slot. }
  1390.         FUNCTION WalkDiagonal (VAR foundWindowRect: Rect; destDeviceRect:Rect;
  1391.             diamondSize, diagNum: INTEGER; VAR slotNum: INTEGER): BOOLEAN;
  1392.         VAR
  1393.             done, junk:             BOOLEAN;
  1394.             testRect:                Rect;
  1395.             windowToStaggerFrom:    WindowPtr;
  1396.             
  1397.             { WindowNotInSlot returns true if there is no window occupying the slot indicated
  1398.               by foundWindowRect. }
  1399.             FUNCTION WindowNotInSlot (VAR foundWindowRect: Rect;
  1400.                 windowToStaggerFrom: WindowPtr): BOOLEAN;
  1401.             VAR
  1402.                 delta, absdelta:            Point;
  1403.                 testRect, staggerFromRect:    Rect;
  1404.             BEGIN { WindowNotInSlot }
  1405.                 WindowNotInSlot := true;
  1406.                 
  1407.                 if WindowPeek(windowToStaggerFrom)^.visible = true then BEGIN
  1408.                     { This window is not invisible.  Staggering from an invisible
  1409.                       window is going to confuse the user, so don't do it. }
  1410.         
  1411.                     staggerFromRect := GetWindowStructureRect(windowToStaggerFrom);
  1412.                     delta.v := staggerFromRect.top  - newWindowRect.top;
  1413.                     delta.h := staggerFromRect.left - newWindowRect.left;
  1414.                     absdelta := delta;
  1415.                     IF delta.v < 0 THEN
  1416.                         absdelta.v := -delta.v;
  1417.                     IF delta.h < 0 THEN
  1418.                         absdelta.h := -delta.h;
  1419.                     IF absdelta.h + absdelta.v < diamondSize THEN BEGIN
  1420.                         IF delta.h + delta.v > 0 THEN
  1421.                             OffsetRect(foundWindowRect, delta.h, delta.v);
  1422.                                 { If the window that took our slot is closer to
  1423.                                   the lower-right corner than we are, then use
  1424.                                   this window's location as the basis for the
  1425.                                   slots from now on.  This will align new windows
  1426.                                   with previous windows that are not gridded to
  1427.                                   the default slot positions.  The check for > 0
  1428.                                   is necessary to prevent bouncing between two
  1429.                                   existing windows.  This check guarantees that
  1430.                                   we are progressing with the evaluation. }
  1431.                         WindowNotInSlot := false;
  1432.                     END;
  1433.                 END; { if window is visible }
  1434.             END; { WindowNotInSlot }
  1435.     
  1436.         BEGIN { WalkDiagonal }
  1437.             slotNum := 0;
  1438.             done := false;
  1439.             WalkDiagonal := true;
  1440.             while NOT done DO BEGIN
  1441.                 junk := SectRect (foundWindowRect, destDeviceRect, testRect);
  1442.                 { We are done if the window is not entirely on destination device }
  1443.                 done := NOT EqualRect (foundWindowRect, testRect);
  1444.                 if NOT done THEN BEGIN
  1445.                     windowToStaggerFrom := FrontWindow;
  1446.                     { Loop through all windows and see if any of them occupy our slot }
  1447.                     while (windowToStaggerFrom <> NIL) & 
  1448.                         WindowNotInSlot (foundWindowRect, windowToStaggerFrom) DO
  1449.                             windowToStaggerFrom := 
  1450.                                 WindowPtr (WindowPeek (windowToStaggerFrom)^.nextWindow);
  1451.                     { If windowToStaggerFrom is now NIL, then we tried all the windows
  1452.                       in this slot and none of them occupied it, so this slot is available. }
  1453.                     if windowToStaggerFrom = NIL THEN
  1454.                         done := true
  1455.                     ELSE BEGIN
  1456.                         { Try next slot }
  1457.                         slotNum := slotNum + 1;
  1458.                         OffsetRect (foundWindowRect, kStaggerH, kStaggerV);
  1459.                     END
  1460.                 END ELSE
  1461.                     WalkDiagonal := false;
  1462.             END
  1463.         END; { WalkDiagonal }
  1464.     
  1465.     BEGIN { StaggerWindow }
  1466.         { If we have a window to stagger from, use the device for that window,
  1467.           else use the device for the window that is getting staggered. }
  1468.         IF relatedWindow = NIL THEN
  1469.             whichDevice := window
  1470.         ELSE
  1471.             whichDevice := relatedWindow;
  1472.  
  1473.         deviceRect := GetWindowDeviceRectNMB(whichDevice);
  1474.             { We now have the rect of the device we want to stagger within. }
  1475.  
  1476.         oldWindowRect := GetWindowStructureRect(window);
  1477.         newWindowRect.top    := deviceRect.top  + kStartPtV;
  1478.         newWindowRect.left   := deviceRect.left + kStartPtH;
  1479.         newWindowRect.bottom := newWindowRect.top  + oldWindowRect.bottom - oldWindowRect.top;
  1480.         newWindowRect.right  := newWindowRect.left + oldWindowRect.right  - oldWindowRect.left;
  1481.             { We now have a new rect for the first window position slot. }
  1482.  
  1483.         slot1 := newWindowRect;
  1484.             { We keep this slot in case we find no acceptable slots.  If we
  1485.               don't find an acceptable one, we will use this one anyway. }
  1486.  
  1487.         if kStaggerH < kStaggerV THEN
  1488.             diamondSize := kStaggerH
  1489.         ELSE
  1490.             diamondSize := kStaggerV;
  1491.  
  1492.         finis := false;
  1493.         vertDirection := true;
  1494.         WHILE NOT finis DO BEGIN
  1495.             finis := WalkDiagonal (newWindowRect, deviceRect, diamondSize, diagNum, slotNum);
  1496.             if NOT finis THEN BEGIN
  1497.                 newWindowRect := slot1;        { Reset newWindowRect }
  1498.                 if slotNum = 0 THEN BEGIN
  1499.                     if vertDirection THEN BEGIN
  1500.                         vertDirection := false;
  1501.                         diagNum := 0;                { Reset diagonal number }
  1502.                     END
  1503.                     ELSE
  1504.                         finis := true;            { Out of possible slots }
  1505.                 END;
  1506.                 diagNum := diagNum + 1;
  1507.                 if NOT finis THEN
  1508.                     if vertDirection THEN
  1509.                         OffsetRect(newWindowRect, 0, diagNum * kStaggerV)
  1510.                     ELSE
  1511.                         OffsetRect(newWindowRect, diagNum * kStaggerH, 0);
  1512.             END
  1513.         END;
  1514.  
  1515.         contentRect := GetWindowContentRect(window);
  1516.             { Get where the window is now. }
  1517.  
  1518.         OffsetRect(contentRect, newWindowRect.left - oldWindowRect.left,
  1519.                                 newWindowRect.top  - oldWindowRect.top);
  1520.             { Calculate the new content rect. }
  1521.  
  1522.         MoveWindow(window, contentRect.left, contentRect.top, false);
  1523.             { Move the window to the new location. }
  1524.  
  1525.  
  1526.         StaggerWindow := contentRect;
  1527.     END; { StaggerWindow }
  1528.  
  1529.  
  1530.  
  1531. {*****************************************************************************}
  1532.  
  1533.  
  1534.  
  1535. {$S UtilMain}
  1536. PROCEDURE StandardAbout(appNameStringID: INTEGER);
  1537.  
  1538.     VAR
  1539.         apNameHndl:         StringHandle;
  1540.         curVersion:         VersRecHndl;
  1541.         apName:             Str255;
  1542.         verNum:             Str255;
  1543.         itemHit:            INTEGER;
  1544.         err:                OSErr;
  1545.  
  1546.     BEGIN
  1547.         IF NOT gUtilitiesInited THEN            { make sure we were inititialized }
  1548.             InitUtilities;
  1549.  
  1550.         apNameHndl := NIL;
  1551.         IF (appNameStringID <> kUseRealAppName) THEN BEGIN
  1552.             IF (appNameStringID <> kUseCreatorString) THEN
  1553.                 apNameHndl := GetString(appNameStringID);
  1554.             IF (apNameHndl = NIL) THEN
  1555.                 apNameHndl := StringHandle(GetAppResource(gSignature, 0, err));
  1556.         END;
  1557.  
  1558.         IF (apNameHndl = NIL) | (appNameStringID = kUseRealAppName) THEN
  1559.             apName := gAppName
  1560.         ELSE
  1561.             apName := apNameHndl^^;
  1562.  
  1563.         curVersion := VersRecHndl(GetAppResource('vers', 1, err));
  1564.         IF curVersion <> NIL THEN BEGIN
  1565.             verNum := StringPtr(ORD(@curVersion^^.shortVersion) + ORD(curVersion^^.
  1566.                                 shortVersion[0]) + 1)^ { get long version string }
  1567.         END
  1568.         ELSE
  1569.             verNum := '????';                        { at least initialize it }
  1570.  
  1571.         ParamText(apName, verNum, '', '');
  1572.  
  1573.         itemHit := CenteredAlert(rStdAboutAlert, NIL);
  1574.     END;                                            { StandardAbout }
  1575.  
  1576.  
  1577.  
  1578. {*****************************************************************************}
  1579.  
  1580.  
  1581.  
  1582. {$S UtilInit}
  1583. PROCEDURE StandardInitialization(callsToMoreMasters: INTEGER);
  1584.  
  1585.     VAR
  1586.         count:                INTEGER;
  1587.  
  1588.     BEGIN
  1589.         InitToolBox;
  1590.  
  1591.         IF callsToMoreMasters > 0 THEN
  1592.             FOR count := 1 TO callsToMoreMasters DO { allocate master pointer blocks }
  1593.                 MoreMasters;
  1594.  
  1595.         PullApplicationToFront;
  1596.  
  1597.         InitUtilities;
  1598.  
  1599.     END;                                            { StandardInitialization }
  1600.  
  1601.  
  1602.  
  1603. {*****************************************************************************}
  1604.  
  1605.  
  1606.  
  1607. {$S UtilInit}
  1608. PROCEDURE StandardMenuSetup(MBARID, AppleMenuID: INTEGER);
  1609.  
  1610.     VAR
  1611.         menuBar:            Handle;
  1612.  
  1613.     BEGIN
  1614.         menuBar := GetNewMBar(MBARID);                { read menus into menu bar }
  1615.         IF menuBar = NIL THEN
  1616.             DeathAlert(rUtilStrings, eNoMenuBar);
  1617.         SetMenuBar(menuBar);                        { install menus }
  1618.         DisposeHandle(menuBar);
  1619.         AppendResMenu(GetMenuHandle(AppleMenuID), 'DRVR'); { add DA names to Apple menu }
  1620.         DrawMenuBar;
  1621.     END;                                            { StandardMenuSetup }
  1622.  
  1623.  
  1624. {*****************************************************************************}
  1625.  
  1626.  
  1627.  
  1628. {$S UtilMain}
  1629. PROCEDURE ToggleCheck(dlgPtr: DialogPtr; chkItem: INTEGER);
  1630.  
  1631.     VAR
  1632.         iKind:                INTEGER;
  1633.         iHandle:            Handle;
  1634.         iRect:                Rect;
  1635.         newValue:            INTEGER;
  1636.  
  1637.     BEGIN
  1638.         GetDialogItem(dlgPtr, chkItem, iKind, iHandle, iRect);
  1639.         newValue := GetControlValue(ControlHandle(iHandle));
  1640.         IF newValue = 0 THEN
  1641.             newValue := 1
  1642.         ELSE
  1643.             newValue := 0;
  1644.         SetControlValue(ControlHandle(iHandle), newValue);
  1645.     END;
  1646.  
  1647.  
  1648.  
  1649. {*****************************************************************************}
  1650.  
  1651.  
  1652.  
  1653. {$S UtilInit}
  1654. FUNCTION TrapExists(theTrap: INTEGER): BOOLEAN;
  1655.  
  1656. { Check to see if a given trap is implemented. This is only used by the
  1657.   Initialize routine in this program, so we put it in the Initialize segment. }
  1658.  
  1659.     VAR
  1660.         theTrapType:        TrapType;
  1661.  
  1662.     BEGIN
  1663.         theTrapType := GetTrapType(theTrap);
  1664.         IF (theTrapType = ToolTrap) THEN BEGIN
  1665.             theTrap := BAND(theTrap, $07FF);
  1666.             IF theTrap >= NumToolboxTraps THEN
  1667.                 theTrap := _Unimplemented;
  1668.         END;
  1669.  
  1670.         TrapExists := NGetTrapAddress(_Unimplemented, ToolTrap) <> NGetTrapAddress(theTrap,
  1671.                       theTrapType);
  1672.     END;                                            { TrapExists }
  1673.  
  1674.  
  1675.  
  1676. {*****************************************************************************}
  1677.  
  1678.  
  1679.  
  1680. {$S UtilMain}
  1681. PROCEDURE    ZoomToWindowDevice(window:WindowPtr; maxWidth,maxHeight,zoomDir:INTEGER; front:BOOLEAN);
  1682.  
  1683. { Zoom the window to the size appropriate for the device that contains the
  1684.   most of the window.  An additional feature is that you can state the
  1685.   maximum that a window should be zoomed, either horizontally or vertically.
  1686.   If you pass in a maximum of 0 for the zoom for either direction, then that
  1687.   direction will be zoomed to fit the device. }
  1688.  
  1689.      VAR
  1690.         oldPort:                                            GrafPtr;
  1691.         contentRect, structureRect, deviceRect, newRect:    Rect;
  1692.         width, height, dx, dy:                                INTEGER;
  1693.  
  1694.     BEGIN
  1695.         GetPort(oldPort);
  1696.         SetPort(window);
  1697.         EraseRect(window^.portRect);         { Recommended for cosmetic reasons. }
  1698.  
  1699.         { If there is the possibility of multiple gDevices, then we must check them to
  1700.           make sure we are zooming onto the right display device when zooming out. }
  1701.  
  1702.         if (zoomDir = inZoomOut) and (gQDVersion > kQDOriginal) THEN BEGIN
  1703.  
  1704.             contentRect      := GetWindowContentRect(window);
  1705.             structureRect := GetWindowStructureRect(window);
  1706.             deviceRect      := GetWindowDeviceRectNMB(window);
  1707.  
  1708.             deviceRect.left   := deviceRect.left   + (contentRect.left - structureRect.left + 2);
  1709.             deviceRect.top    := deviceRect.top    + (contentRect.top - structureRect.top + 2);
  1710.             deviceRect.right  := deviceRect.right  - (structureRect.right - contentRect.right + 2);
  1711.             deviceRect.bottom := deviceRect.bottom - (structureRect.bottom - contentRect.bottom + 2);
  1712.             newRect := deviceRect;
  1713.  
  1714.             if maxWidth > 0 THEN BEGIN
  1715.                 width := deviceRect.right - deviceRect.left;
  1716.                 if width > maxWidth THEN BEGIN
  1717.                     newRect.left  := contentRect.left;
  1718.                     newRect.right := newRect.left + maxWidth;
  1719.                 END;
  1720.             END;
  1721.             if maxHeight > 0 THEN BEGIN
  1722.                 height := deviceRect.bottom - deviceRect.top;
  1723.                 if height > maxHeight THEN BEGIN
  1724.                     newRect.top    := contentRect.top;
  1725.                     newRect.bottom := newRect.top + maxHeight;
  1726.                 END;
  1727.             END;
  1728.             dx := deviceRect.left - newRect.left;
  1729.             if dx < 0 THEN BEGIN
  1730.                 dx := deviceRect.right - newRect.right;
  1731.                 if dx > 0 THEN
  1732.                     dx := 0;
  1733.             END;
  1734.             dy := deviceRect.top - newRect.top;
  1735.             if dy < 0 THEN BEGIN
  1736.                 dy := deviceRect.bottom - newRect.bottom;
  1737.                 if dy > 0 THEN
  1738.                     dy := 0;
  1739.             END;
  1740.             OffsetRect(newRect, dx, dy);
  1741.  
  1742.             WStateDataHandle(WindowPeek(window)^.dataHandle)^^.stdState := newRect;
  1743.                 { Set up the WStateData record for this window. }
  1744.         END;
  1745.  
  1746.         ZoomWindow(window, zoomDir, front);
  1747.         SetPort(oldPort);
  1748.     END;
  1749.  
  1750.  
  1751.